/**
 * UltraCSA平台系统文件
 * 
 * Copyright 2016 北京神州泰岳软件股份有限公司
 */
package com.ultrapower.ultracsa.product.service.impl;

import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.annotation.Resource;
import javax.enterprise.inject.New;

import org.apache.commons.beanutils.PropertyUtilsBean;
import org.apache.log4j.Logger;
import org.apache.xmlbeans.impl.jam.mutable.MPackage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.support.RequestContext;
 









import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ultrapower.ultracsa.product.dao.KickstartDao;
import com.ultrapower.ultracsa.product.dao.ModelDao;
import com.ultrapower.ultracsa.product.dao.UploadDao;
import com.ultrapower.ultracsa.product.pojo.IPLog;
import com.ultrapower.ultracsa.product.pojo.InstallPackage;
import com.ultrapower.ultracsa.product.pojo.Iso;
import com.ultrapower.ultracsa.product.pojo.KickStart;
import com.ultrapower.ultracsa.product.pojo.KickstartLog;
import com.ultrapower.ultracsa.product.pojo.PackageGroup;
import com.ultrapower.ultracsa.product.pojo.ShellFile;
import com.ultrapower.ultracsa.product.service.OSDeployService;

/**
 * 作者: GuoPengFei
 * 
 * 日期: 2016 4 25
 * 
 * 版权说明：北京神州泰岳软件股份有限公司
 * 
 * TODO 源码说明
 */
@Service("OSDeployImpl")
@Transactional
public class OSDeployImpl implements OSDeployService {

	private static final String PATH = OSDeployImpl.class.getClassLoader()
			.getResource("/").getPath();

	private Logger logger = Logger.getLogger(OSDeployImpl.class);
	@Resource
	private KickstartDao kickstartDao;
	@Resource
	private UploadDao uploadDao;

	@Resource
	private ModelDao modelDao;

	@Override
	public List<KickStart> kickStartList() {
		return this.kickstartDao.kickStartList();
	}

	@Override
	public void insertKickStart(KickStart kickStart) {
		// TODO Auto-generated method stub

	}

	@Override
	public void updateKickStart(KickStart kickStart) {
		// TODO Auto-generated method stub

	}
	
	/**
	 * 
	 * 分页查询
	 * 
	 * @param ks_search 要查询的ks名称
	 * @param currentPage 当前页码
	 * 
	 */
	public Map<String, Object> KsList(String ks_search, int currentPage,
			int rows){
		PageHelper.startPage(currentPage, rows);
		
		List<KickStart> list = kickstartDao.KsList(ks_search);
		PageInfo page = new PageInfo(list);
		long tottle = page.getTotal();
		List<Map<String, Object>> reList = new ArrayList<Map<String, Object>>();
		Map<String, Object> map1 = null;
		if(list !=null && !list.isEmpty()){
			for(KickStart kickStart :list ){
				map1 = beanToMap(kickStart);
				reList.add(map1);
			}
		}
		Map<String, Object> map = new HashMap<String, Object>();
//		System.out.println("总共" + tottle + "行,显示" + list.size() + "行");
		map.put("totalCount", tottle);
		map.put("ksList", reList);
		map.put("currentPage", currentPage);
		return map;
	}
	/**
	 * 批量删除kickstart文件
	 * 
	 * @param map
	 *            要删除的信息
	 */
	@Override
	public Map<String, Object> delteKickStarts(Map<String, String> map) {
		Map<String, Object> returnMap = new HashMap<String, Object>();
		String[] ids = map.get("ids").split(",");
		Integer[] ia = new Integer[ids.length];
		KickStart kickStart = null;
		for (int i = 0; i < ids.length; i++) {
			ia[i] = Integer.parseInt(ids[i]);
			kickStart = kickstartDao.findKickStartById(ia[i]);
			deleteFile(kickStart);
		}
		kickstartDao.batchDeleteKickstarts(Arrays.asList(ia));
		kickstartDao.batchDeleteKicAndShell(Arrays.asList(ia));
		kickstartDao.batchDeleteKicLog(Arrays.asList(ia));
		
		// 需要删除kickstart的日志数据
		// kickstartDao.batchDeleteIpLogs(Arrays.asList(ia));
		returnMap.put("result", true);
		return returnMap;
	}

	/**
	 * 删除kickstart配置文件
	 * 
	 * @param kickStart
	 */
	private void deleteFile(KickStart kickStart) {
		if (kickStart == null)
			return;
		Date date = kickStart.getCreateTime();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		String filePath = PATH.split("classes")[0];
		filePath += "file" + File.separator + "kickstart" + File.separator
				+ kickStart.getUserAccount() + dateFormat.format(date)
				+ ".properties";

		File file = new File(filePath);
		if (file.isFile())
			file.delete();
	}

	@Override
	public List<String> findIsoList() {
		List<Iso> list = uploadDao.findIso();
		List<String> osNameList = new ArrayList<String>();

		if (list != null && !list.isEmpty()) {

			for (Iso iso : list) {
				String isoName = iso.getIsoName();
				int id = iso.getCsaId();
				osNameList.add(iso.getIsoName() + "-$-" + id);
			}
		}
		return osNameList;
	}

	@Override
	public Map<String, Object> packagesList() {
		Map<String, Object> map = new HashMap<String, Object>();
		List<PackageGroup> groupList = kickstartDao.packageGroupList();
		List<Map<String, Object>> reList = null;
		if (groupList != null && !groupList.isEmpty()) {
			for (PackageGroup packageGroup : groupList) {
				reList = findPackagesById(packageGroup.getCsaId());
				map.put(packageGroup.getGroupName(), reList);
			}
		}
		return map;
	}

	public List<Map<String, Object>> findPackagesById(Integer groupCsaid) {
		List<Map<String, Object>> reList = new ArrayList<Map<String, Object>>();

		List<InstallPackage> installPackages = kickstartDao
				.findPackagesById(groupCsaid);

		if (installPackages != null && !installPackages.isEmpty()) {
			for (InstallPackage installPackage : installPackages) {
				reList.add(beanToMap(installPackage));
			}
		}
		return reList;
	}

	/**
	 * 根据反射机制获取对象的所有属性的值并封装成map
	 * 
	 * @param obj
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	private Map<String, Object> beanToMap(Object obj) {
		Map<String, Object> params = new HashMap<String, Object>(0);
		try {
			PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
			PropertyDescriptor[] descriptors = propertyUtilsBean
					.getPropertyDescriptors(obj);
			for (int i = 0; i < descriptors.length; i++) {
				String name = descriptors[i].getName();
				if (!"class".equals(name)) {
					Class type = descriptors[i].getPropertyType();
					String value = "";
					if (type.equals(Date.class)) {
						Date date = (Date) propertyUtilsBean.getNestedProperty(
								obj, name);
						// SimpleDateFormat df=new
						// SimpleDateFormat("yyyy-MM-dd HH:MM:ss");
						SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd");
						value = df.format(date);
					} else if(type.equals(Iso.class)){
						Iso iso =(Iso) propertyUtilsBean.getNestedProperty(obj, name);
						value = iso.getIsoName();
					}else{
						value = String.valueOf(propertyUtilsBean
								.getNestedProperty(obj, name));
					}
					params.put(name, value);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return params;
	}

	public Map<String, Object> findAllShell() {
		Map<String, Object> map = new HashMap<String, Object>();
		List<ShellFile> list = modelDao.ShellFileList();
		if (list != null && !list.isEmpty()) {
			for (ShellFile shellFile : list) {
				insertMap(map, shellFile);
			}
		}
		return map;
	}

	@SuppressWarnings("unchecked")
	private void insertMap(Map<String, Object> map, ShellFile shellFile) {
		String fileType = shellFile.getFileType();
		List<ShellFile> list = null;
		if (map.containsKey(fileType)) {
			// map.put(fileType, ((List<ShellFile>)
			// map.get(fileType)).add(shellFile));
			list = (List<ShellFile>) map.get(fileType);
			list.add(shellFile);
			map.put(fileType, list);
		} else {
			list = new ArrayList<ShellFile>();
			list.add(shellFile);
			map.put(fileType, list);
		}
	}

	@SuppressWarnings("unchecked")
	public Map<String, Object> editKickstart(Map<String, Object> map,
			String userName,RequestContext requestContext) {
		Map<String, String> kickMap = new HashMap<String, String>();
		String userIp = (String) map.get("userIp");
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		String filePath = PATH.split("classes")[0];

		String opType = (String) map.get("opType");
		String conf_name = (String) map.get("conf_name");

		kickMap.put("langue", (String) map.get("lan_in"));

		String osString = (String) map.get("iso_name");
		osString.substring(0, osString.lastIndexOf("."));
		kickMap.put("osName", osString);

		kickMap.put("timezone", (String) map.get("time_zone"));

		boolean radom_pwd = (boolean) map.get("radom_pwd");
		String rootpwd = "";
		if (radom_pwd)
			// 自动生成跟密码
			rootpwd = "1234567";
		else
			rootpwd = (String) map.get("root_pwd");

		kickMap.put("rootpwd", rootpwd);

		String note = (String) map.get("note"); 

		boolean reboot_ch = (boolean) map.get("reboot_ch");
		kickMap.put("reboot", reboot_ch ? "reboot" : "");

		List<Map<String, String>> discPartList = (List<Map<String, String>>) map
				.get("discPart");
		StringBuffer stringBuffer = new StringBuffer();

		for (Map<String, String> parMap : discPartList) {
			stringBuffer.append(parMap.get("raid")).append(",")
					.append(parMap.get("type")).append(",")
					.append(parMap.get("size")).append(";");
		}
		kickMap.put("partitions", (0 == stringBuffer.length()) ? ""
				: stringBuffer.substring(0, stringBuffer.length() - 1));

		String insSoft = ((List<String>) map.get("insSoft")).toString();
		kickMap.put("packages", insSoft.substring(1, insSoft.length() - 1));

		List<String> shellList = (List<String>) map.get("shellFile");
		List<Map<String, Integer>> tempList = new ArrayList<Map<String, Integer>>();
		KickstartLog kickstartLog =null;
		KickStart kickStart = null;
		if (opType.equals("update")) {
			String temp = (String) map.get("csaId");
			Integer csaId = Integer.parseInt(temp);
			kickStart = kickstartDao.findKickStartById(csaId);
			filePath += "file" + File.separator + "kickstart" + File.separator
					+ kickStart.getUserAccount()
					+ dateFormat.format(kickStart.getCreateTime())
					+ ".properties";
			kickStart.setKsName(conf_name);
			kickStart.setIso(modelDao.getISOByName(osString));
			kickstartDao.updateKickStart(kickStart);
			kickstartDao.deleteShellKs(kickStart.getCsaId());
			kickstartLog = instanceIpLogs(kickStart.getCsaId(), note, userName, userIp);
			kickstartDao.insertKsLog(kickstartLog);
		}else{
			Date date = new Date();
			kickStart = new KickStart();
			kickStart.setCreateTime(date);
			kickStart.setKsName(conf_name);
			kickStart.setIso(modelDao.getISOByName(osString));
			kickStart.setUserAccount(userName);
			kickstartDao.insertKickStart(kickStart);
			filePath += "file" + File.separator + "kickstart" + File.separator
					+ userName + dateFormat.format(kickStart.getCreateTime())
					+ ".properties";
		}
		if(shellList !=null && !shellList.isEmpty()){
			Map<String, Integer> tempMap = null;
			for(String shellId : shellList){
				tempMap = new HashMap<String, Integer>();
				tempMap.put("shellId", Integer.parseInt(shellId));
				tempMap.put("ksId",kickStart.getCsaId());
				tempList.add(tempMap);
			}
		}
		if(tempList !=null && tempList.size() > 0){
			kickstartDao.insertKickStartShell(tempList);
		}
		
		Map<String, Object> map1 = writeData(filePath, kickMap,requestContext);
		
		return map1;
	}
	/**
	 * 实例化ks log
	 * @param ksCsaId
	 * @param notes
	 * @param userAccount
	 * @param userIp
	 * @return
	 */
	private KickstartLog instanceIpLogs(int ksCsaId, String notes, String userAccount,
			String userIp) {
		KickstartLog kickstartLog = new KickstartLog(userAccount, new Date(), userIp, notes, ksCsaId);
		return kickstartLog;
	}
	/**
	 * 修改或添加键值对 如果key存在，修改, 反之，添加。
	 * 
	 * @param filePath
	 *            文件路径，即文件所在包的路径，例如：java/util/config.properties
	 * @param map
	 *            键值对集合
	 */
	public Map<String,Object> writeData(String filePath, Map<String, String> map,RequestContext requestContext) {
		Map<String,Object> map2 = new HashMap<String,Object>();
		Properties prop = new Properties();
		try {
			File file = new File(filePath);
			if (!file.exists())
				file.createNewFile();
			InputStream fis = new FileInputStream(file);
			prop.load(fis);
			// 一定要在修改值之前关闭fis
			fis.close();
			OutputStream fos = new FileOutputStream(filePath);
			Iterator<String> iterator = map.keySet().iterator();
			while (iterator.hasNext()) {
				String key = iterator.next();
				prop.setProperty(key, map.get(key));
			}
			// 保存，并加入注释
			prop.store(fos, "");
			fos.close();
		} catch (IOException e) {
			String fileError4 = requestContext.getMessage("fileError4");
			Object [] parameter = {filePath};
			String msg1 = MessageFormat.format(fileError4, parameter); 
			logger.error(msg1);
			map2.put("result", false);
			map2.put("errorMsg", msg1);
//			e.printStackTrace();
			return map2;
		}
		map2.put("result", true);
		return map2;
	}

	@SuppressWarnings("unused")
	@Override
	public Map<String, Object> getKsFile(Map<String, String> map,RequestContext requestContext) {

		Map<String, Object> returnMap = new HashMap<String, Object>();

		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		Integer csaId = Integer.parseInt(map.get("id"));
		KickStart kickStart = kickstartDao.findKickStartById(csaId);
		String filePath = PATH.split("classes")[0] + "file" + File.separator
				+ "kickstart" + File.separator + kickStart.getUserAccount()
				+ dateFormat.format(kickStart.getCreateTime()) + ".properties";
		Properties pro = null;
		FileInputStream in = null;
		try {
			in = new FileInputStream(filePath);
			pro = new Properties();
			pro.load(in);
		} catch (FileNotFoundException e) {
			String fileError1 = requestContext.getMessage("fileError1");
			Object [] parameter = {filePath};
			String msg1 = MessageFormat.format(fileError1, parameter); 
			logger.error(msg1);
			returnMap.put("result", false);
			returnMap.put("errorMsg",msg1);
			return returnMap;
		} catch (IOException e1) {
			String fileError2 = requestContext.getMessage("fileError2");
			Object [] parameter = {filePath};
			String msg1 = MessageFormat.format(fileError2, parameter);
			logger.error(msg1);
			returnMap.put("result", false);
			returnMap.put("errorMsg", msg1);
			return returnMap;
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		if (pro == null) {
			String fileError2 = requestContext.getMessage("fileError2");
			Object [] parameter = {filePath};
			String msg1 = MessageFormat.format(fileError2, parameter);
			returnMap.put("result", false);
			returnMap.put("errorMsg", msg1);
			return returnMap;
		}

		String rootpwd = pro.getProperty("rootpwd", "");
		String reboot = pro.getProperty("reboot", "");
		String timezone = pro.getProperty("timezone", "Asia/Shanghai");
		String osName = pro.getProperty("osName", "");
		String langue = pro.getProperty("langue", "zh_CN");

		String partitions = pro.getProperty("partitions", ""); // /,ext4,100000;/home,ext4,100000;/home,ext4,100000
		List<Map<String, String>> partList = new ArrayList<Map<String, String>>();
		if (!partitions.equals("")) {
			String[] maps = partitions.split(";");
			Map<String, String> map2 = null;
			for (String evPart : maps) {
				map2 = new HashMap<String, String>();
				String[] par = evPart.split(",");
				map2.put("raid", par[0].trim());
				map2.put("type", par[1].trim());
				map2.put("size", par[2].trim());
				partList.add(map2);
			}
		}

		List<Map<String, Object>> postList = new ArrayList<Map<String, Object>>();
		Integer kic = kickStart.getCsaId();
		List<ShellFile> tempList = kickstartDao.getShellByKicstartId(kic);
		if(tempList !=null && !tempList.isEmpty()){
			for(ShellFile shellFile : tempList){
				postList.add(beanToMap(shellFile));
			}
		}
//		String post = pro.getProperty("post", "");
//		List<Map<String, String>> postList = new ArrayList<Map<String, String>>();
//		if (!post.equals("")) {
//			String[] pos = post.split(",");
//			ShellFile shellFile = null;
//			Map<String, String> map2 = null;
//			for (String po : pos) {
//				map2 = new HashMap<String, String>();
//				shellFile = modelDao.getShellFileByName(po.trim());
//				map2.put("csaID", String.valueOf(shellFile.getCsaID()));
//				map2.put("fileName", shellFile.getFileName());
//				postList.add(map2);
//			}
//		}

		String allPackages = pro.getProperty("packages", "");
		List<Map<String, Object>> packageList = new ArrayList<Map<String, Object>>();
		if (!allPackages.equals("")) {
			String[] packages = allPackages.split(",");
			InstallPackage installPackage = null;
			Map<String, Object> pacMap = null;
			for (String package1 : packages) {
				installPackage = kickstartDao.findKickStartPacById(Integer.parseInt(package1.trim()));
				pacMap =  beanToMap(installPackage);
				packageList.add(pacMap);
			}
		}
		returnMap.put("rootpwd", rootpwd);
		returnMap.put("reboot", reboot);
		returnMap.put("osName", osName);
		returnMap.put("timezone", timezone);
		returnMap.put("langue", langue);
		returnMap.put("partitions", partList);
		returnMap.put("post", postList);
		returnMap.put("packages", packageList);
		returnMap.put("result", true);
		returnMap.put("conf_name", kickStart.getKsName());
		returnMap.put("iso_name", kickStart.getIso().getIsoName());
		return returnMap;
	}

	@Override
	public Map<String, Object> copyKickstart(Map<String, String> map,RequestContext requestContext) {
		Map<String, Object> returnMap = new HashMap<String,Object>();
		String user = map.get("user");
		String iso_name = map.get("iso_name");
		String conf_name = map.get("conf_name");
		String tempId = map.get("csaId");
		Integer csaId = Integer.parseInt(tempId);
		KickStart kickStart = kickstartDao.findKickStartById(csaId);
		
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		String filePath = PATH.split("classes")[0];
		String srcFile = filePath+ "file" + File.separator + "kickstart" + File.separator
				+ kickStart.getUserAccount()
				+ dateFormat.format(kickStart.getCreateTime()) + ".properties";
		Date createDate = new Date();
		String destFile = filePath+ "file" + File.separator + "kickstart" + File.separator
				+ user
				+ dateFormat.format(createDate) + ".properties";
		
		kickStart.setCreateTime(createDate);
		Integer oldCsa = kickStart.getCsaId();
		kickStart.setCsaId(null);
		Iso iso = modelDao.getISOByName(iso_name.trim());
		kickStart.setIso(iso);
		kickStart.setKsName(conf_name);
		kickstartDao.insertKickStart(kickStart);
		
//		Map<String, Integer> dddMap = new HashMap<String ,Integer>();
//		map.put("", value)
		kickstartDao.copytKickStartShell(kickStart.getCsaId(),oldCsa);
		boolean copyResult = copyFile(srcFile, destFile, true);
		if(!copyResult){
			//拷贝失败
			String fileError3 = requestContext.getMessage("fileError3");
			Object [] parameter = {srcFile,destFile};
			String msg1 = MessageFormat.format(fileError3, parameter); 
			returnMap.put("result", false);
			returnMap.put("errorMsg", msg1);
			return  returnMap;
		}

		Map<String, String> tempMap = new HashMap<String,String>();
		tempMap.put("osName", iso_name);
		writeData(destFile, tempMap,requestContext);
		returnMap.put("result", true);
		return  returnMap;
	}

	/**
	 * 复制单个文件
	 * 
	 * @param srcFileName
	 *            待复制的文件名
	 * @param descFileName
	 *            目标文件名
	 * @param overlay
	 *            如果目标文件存在，是否覆盖
	 * @return 如果复制成功返回true，否则返回false
	 */
	private boolean copyFile(String srcFileName, String destFileName,
			boolean overlay) {
		File srcFile = new File(srcFileName);

		// 判断源文件是否存在
		if (!srcFile.exists()) {
			logger.error("源文件：" + srcFileName + "不存在！");
			return false;
		} else if (!srcFile.isFile()) {
			logger.error("复制文件失败，源文件：" + srcFileName + "不是一个文件！");
			return false;
		}

		// 判断目标文件是否存在
		File destFile = new File(destFileName);
		if (destFile.exists()) {
			// 如果目标文件存在并允许覆盖
			if (overlay) {
				// 删除已经存在的目标文件，无论目标文件是目录还是单个文件
				new File(destFileName).delete();
			}
		} else {
			// 如果目标文件所在目录不存在，则创建目录
			if (!destFile.getParentFile().exists()) {
				// 目标文件所在目录不存在
				if (!destFile.getParentFile().mkdirs()) {
					// 复制文件失败：创建目标文件所在目录失败
					return false;
				}
			}
		}

		// 复制文件
		int byteread = 0; // 读取的字节数
		InputStream in = null;
		OutputStream out = null;

		try {
			in = new FileInputStream(srcFile);
			out = new FileOutputStream(destFile);
			byte[] buffer = new byte[1024];

			while ((byteread = in.read(buffer)) != -1) {
				out.write(buffer, 0, byteread);
			}
			return true;
		} catch (FileNotFoundException e) {
			return false;
		} catch (IOException e) {
			return false;
		} finally {
			try {
				if (out != null)
					out.close();
				if (in != null)
					in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
